package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.AroundSign;
import com.myk.game.gobangchess.signs.TextSign;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 王步四子棋房间
 */
public class King4GoRoom extends Room {

    private int[] firstPoint;//黑方第一颗棋子的位置
    private int[] lastPoint;//记录上一子的位置

    public King4GoRoom(String roomName) {
        super(roomName, "\t\t新棋吧友螃蟹设计的连珠类新棋。", "王步四子棋", BoardStyleData.getGoBangStyle(17, 17), true, true);
    }

    @Override
    public String getRuleText() {
        return "黑白双方轮流落子，除第一个棋子外，只能落在对方上一手棋子周围一格。\n" +
                "形成连四珠获胜，无法落子判负。\n" +
                "特殊的，黑方第一个棋子参与形成连珠时，要连五才能获胜。";
    }

    @Override
    public String getGameInfo() {
        signList.clear();
        if (firstPoint != null) {
            signList.add(new TextSign(getIndex(firstPoint[0], firstPoint[1]), "H", "#FFFF0000"));
        }
        if (lastPoint != null) {
            beautiKing();
        }
        return super.getGameInfo();
    }

    //绘制王位可落子区域
    private void beautiKing() {
        int[][] kingMoves = {{-1, 1}, {-1, 0}, {-1, -1}, {0, 1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}};
        List<Integer> indexes = new ArrayList<Integer>();
        for (int[] move : kingMoves) {
            int nextRow = lastPoint[0] + move[0];
            int nextCol = lastPoint[1] + move[1];
            if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0) {
                indexes.add(getIndex(nextRow, nextCol));
            }
        }
        signList.add(new AroundSign(indexes, "#4400FF00", "#FF00FF00", 1.2f));
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        firstPoint = null;
        lastPoint = null;
    }

    @Override
    public void doRule(int row, int col, int value) {


        if (curGrids[row][col] == 0) { //只能落在空位置
            if (step == 0) {
                firstPoint = new int[]{row, col};
            }
            if (lastPoint != null) {
                if (!isValidKing(row, col)) {
                    return;
                }
            }
            lastPoint = new int[]{row, col};
            curGrids[row][col] = value; //实际落子
            stepAdd(); //步数统计加增加

            //黑方落子时
            if (value == 1) {
                if (checkFormation(1) > 0) {//黑方连成功
                    doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋连成战胜" + player_white.getNickNameOrTemp());
                }
                else {
                    if (!isHasEmptyInKing()) {//当无路可走时判负
                        doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋堵死白棋" + player_white.getNickNameOrTemp());
                    }
                    else {
                        noticeWhiteMove();
                    }
                }
            }

            //白方落子时
            else if (value == 2) {
                if (checkFormation(2) > 0) {
                    doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
                }
                else {
                    if (!isHasEmptyInKing()) {
                        doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋堵死黑棋" + player_black.getNickNameOrTemp());
                    }
                    else {
                        noticeBlackMove();
                    }
                }
            }

        }
    }

    //判断指定位置是否在上一步的王位
    private boolean isValidKing(int row, int col) {
        boolean valid = false;
        if ((Math.abs(lastPoint[0] - row) == 1 && Math.abs(lastPoint[1] - col) == 1) ||
                (Math.abs(lastPoint[0] - row) == 1 && Math.abs(lastPoint[1] - col) == 0) ||
                (Math.abs(lastPoint[0] - row) == 0 && Math.abs(lastPoint[1] - col) == 1)) {
            valid = true;
        }
        return valid;
    }

    //判单指定位王位是否有空位
    private boolean isHasEmptyInKing() {
        int[][] kingMoves = {{-1, 1}, {-1, 0}, {-1, -1}, {0, 1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}};
        List<Integer> indexes = new ArrayList<Integer>();
        for (int[] move : kingMoves) {
            int nextRow = lastPoint[0] + move[0];
            int nextCol = lastPoint[1] + move[1];
            if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0 && curGrids[nextRow][nextCol] == 0) {
                indexes.add(getIndex(nextRow, nextCol));
            }
        }
        return indexes.size() > 0;
    }

    //判断是否连珠（黑方第一颗棋子不参与连4）
    private int checkFormation(int value) {
        int a = checkFormationA(value);
        int b = checkFormationB(value);
        return a + b;
    }

    //获取成4的次数 （长连只算一个）（非通用，本棋特点，一行内只会出现一个连五才能这样写）
    private int checkFormationA(int value) {
        int live = 4; //默认活4
        int liveS = live - 1;

        int rows = curGrids.length;
        int cols = curGrids[0].length;
        int formationCount = 0;

        // 水平方向
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols - liveS; j++) {
                int length = 0;
                for (int k = j; k < j + live; k++) {
                    if (value == 1 && firstPoint != null && i == firstPoint[0] && k == firstPoint[1]) {
                        break;
                    }
                    if (curGrids[i][k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= live) {
                    formationCount += 1;
                    break;
                }
            }
        }

        // 垂直方向
        for (int i = 0; i < rows - liveS; i++) {
            for (int j = 0; j < cols; j++) {
                int length = 0;
                for (int k = i; k < i + live; k++) {
                    if (value == 1 && firstPoint != null && k == firstPoint[0] && j == firstPoint[1]) {
                        break;
                    }
                    if (curGrids[k][j] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= live) {
                    formationCount += 1;
                    break;
                }
            }
        }

        // 左上到右下方向
        for (int i = 0; i < rows - liveS; i++) {
            for (int j = 0; j < cols - liveS; j++) {
                int length = 0;
                for (int k = 0; k < live; k++) {
                    if (value == 1 && firstPoint != null && (i + k) == firstPoint[0] && (j + k) == firstPoint[1]) {
                        break;
                    }
                    if (curGrids[i + k][j + k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= live) {
                    formationCount += 1;
                    break;
                }
            }
        }

        // 右上到左下方向
        for (int i = 0; i < rows - liveS; i++) {
            for (int j = liveS; j < cols; j++) {
                int length = 0;
                for (int k = 0; k < live; k++) {
                    if (value == 1 && firstPoint != null && (i+k) == firstPoint[0] && (j-k) == firstPoint[1]) {
                        break;
                    }
                    if (curGrids[i + k][j - k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= live) {
                    formationCount += 1;
                    break;
                }
            }
        }

        return formationCount;
    }

    //获取成5的次数 （长连只算一个）（非通用，本棋特点，一行内只会出现一个连五才能这样写）
    private int checkFormationB(int value) {
        int live = 5;
        int liveS = live - 1;

        int rows = curGrids.length;
        int cols = curGrids[0].length;
        int formationCount = 0;

        // 水平方向
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols - liveS; j++) {
                int length = 0;
                for (int k = j; k < j + live; k++) {
                    if (curGrids[i][k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= live) {
                    formationCount += 1;
                    break;
                }
            }
        }

        // 垂直方向
        for (int i = 0; i < rows - liveS; i++) {
            for (int j = 0; j < cols; j++) {
                int length = 0;
                for (int k = i; k < i + live; k++) {
                    if (curGrids[k][j] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= live) {
                    formationCount += 1;
                    break;
                }
            }
        }

        // 左上到右下方向
        for (int i = 0; i < rows - liveS; i++) {
            for (int j = 0; j < cols - liveS; j++) {
                int length = 0;
                for (int k = 0; k < live; k++) {
                    if (curGrids[i + k][j + k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= live) {
                    formationCount += 1;
                    break;
                }
            }
        }

        // 右上到左下方向
        for (int i = 0; i < rows - liveS; i++) {
            for (int j = liveS; j < cols; j++) {
                int length = 0;
                for (int k = 0; k < live; k++) {
                    if (curGrids[i + k][j - k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= live) {
                    formationCount += 1;
                    break;
                }
            }
        }

        return formationCount;
    }
}
